home *** CD-ROM | disk | FTP | other *** search
/ Eagles Nest BBS 7 / Eagles_Nest_Mac_Collection_Disc_7.TOAST / General Communication / Y&ZmodemC / zm.c < prev    next >
Text File  |  1989-01-10  |  15KB  |  778 lines

  1. /*
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    05-09-88  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * Entry point Functions:
  7.  *    zsbhdr(type, hdr) send binary header
  8.  *    zshhdr(type, hdr) send hex header
  9.  *    zgethdr(hdr, eflag) receive header - binary or hex
  10.  *    zsdata(buf, len, frameend) send data
  11.  *    zrdata(buf, len) receive data
  12.  *    stohdr(pos) store position data in Txhdr
  13.  *    long rclhdr(hdr) recover position offset from header
  14.  */
  15.  
  16. #ifndef CANFDX
  17. #include "zmodem.h"
  18. int Rxtimeout = 100;        /* Tenths of seconds to wait for something */
  19. #endif
  20.  
  21. #ifndef UNSL
  22. #define UNSL
  23. #endif
  24.  
  25.  
  26. /* Globals used by ZMODEM functions */
  27. int Rxframeind;        /* ZBIN ZBIN32, or ZHEX type of frame received */
  28. int Rxtype;        /* Type of header received */
  29. int Rxcount;        /* Count of data bytes received */
  30. char Rxhdr[4];        /* Received header */
  31. char Txhdr[4];        /* Transmitted header */
  32. long Rxpos;        /* Received file position */
  33. long Txpos;        /* Transmitted file position */
  34. int Txfcs32;        /* TURE means send binary frames with 32 bit FCS */
  35. int Crc32t;        /* Display flag indicating 32 bit CRC being sent */
  36. int Crc32;        /* Display flag indicating 32 bit CRC being received */
  37. int Znulls;        /* Number of nulls to send at beginning of ZDATA hdr */
  38. char Attn[ZATTNLEN+1];    /* Attention string rx sends to tx on err */
  39.  
  40. static lastsent;    /* Last char we sent */
  41. static Not8bit;        /* Seven bits seen on header */
  42.  
  43. static char *frametypes[] = {
  44.     "Carrier Lost",        /* -3 */
  45.     "TIMEOUT",        /* -2 */
  46.     "ERROR",        /* -1 */
  47. #define FTOFFSET 3
  48.     "ZRQINIT",
  49.     "ZRINIT",
  50.     "ZSINIT",
  51.     "ZACK",
  52.     "ZFILE",
  53.     "ZSKIP",
  54.     "ZNAK",
  55.     "ZABORT",
  56.     "ZFIN",
  57.     "ZRPOS",
  58.     "ZDATA",
  59.     "ZEOF",
  60.     "ZFERR",
  61.     "ZCRC",
  62.     "ZCHALLENGE",
  63.     "ZCOMPL",
  64.     "ZCAN",
  65.     "ZFREECNT",
  66.     "ZCOMMAND",
  67.     "ZSTDERR",
  68.     "xxxxx"
  69. #define FRTYPES 22    /* Total number of frame types in this array */
  70.             /*  not including psuedo negative entries */
  71. };
  72.  
  73. static char badcrc[] = "Bad CRC";
  74.  
  75. /* Send ZMODEM binary header hdr of type type */
  76. zsbhdr(type, hdr)
  77. register char *hdr;
  78. {
  79.     register int n;
  80.     register unsigned short crc;
  81.  
  82.     vfile("zsbhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  83.     if (type == ZDATA)
  84.         for (n = Znulls; --n >=0; )
  85.             xsendline(0);
  86.  
  87.     xsendline(ZPAD); xsendline(ZDLE);
  88.  
  89.     if (Crc32t=Txfcs32)
  90.         zsbh32(hdr, type);
  91.     else {
  92.         xsendline(ZBIN); zsendline(type); crc = updcrc(type, 0);
  93.  
  94.         for (n=4; --n >= 0; ++hdr) {
  95.             zsendline(*hdr);
  96.             crc = updcrc((0377& *hdr), crc);
  97.         }
  98.         crc = updcrc(0,updcrc(0,crc));
  99.         zsendline(crc>>8);
  100.         zsendline(crc);
  101.     }
  102.     if (type != ZDATA)
  103.         flushmo();
  104. }
  105.  
  106.  
  107. /* Send ZMODEM binary header hdr of type type */
  108. zsbh32(hdr, type)
  109. register char *hdr;
  110. {
  111.     register int n;
  112.     register UNSL long crc;
  113.  
  114.     xsendline(ZBIN32);  zsendline(type);
  115.     crc = 0xFFFFFFFFL; crc = UPDC32(type, crc);
  116.  
  117.     for (n=4; --n >= 0; ++hdr) {
  118.         crc = UPDC32((0377 & *hdr), crc);
  119.         zsendline(*hdr);
  120.     }
  121.     crc = ~crc;
  122.     for (n=4; --n >= 0;) {
  123.         zsendline((int)crc);
  124.         crc >>= 8;
  125.     }
  126. }
  127.  
  128. /* Send ZMODEM HEX header hdr of type type */
  129. zshhdr(type, hdr)
  130. register char *hdr;
  131. {
  132.     register int n;
  133.     register unsigned short crc;
  134.  
  135.     vfile("zshhdr: %s %lx", frametypes[type+FTOFFSET], rclhdr(hdr));
  136.     sendline(ZPAD); sendline(ZPAD); sendline(ZDLE); sendline(ZHEX);
  137.     zputhex(type);
  138.     Crc32t = 0;
  139.  
  140.     crc = updcrc(type, 0);
  141.     for (n=4; --n >= 0; ++hdr) {
  142.         zputhex(*hdr); crc = updcrc((0377 & *hdr), crc);
  143.     }
  144.     crc = updcrc(0,updcrc(0,crc));
  145.     zputhex(crc>>8); zputhex(crc);
  146.  
  147.     /* Make it printable on remote machine */
  148.     sendline(015); sendline(0212);
  149.     /*
  150.      * Uncork the remote in case a fake XOFF has stopped data flow
  151.      */
  152.     if (type != ZFIN && type != ZACK)
  153.         sendline(021);
  154.     flushmo();
  155. }
  156.  
  157. /*
  158.  * Send binary array buf of length length, with ending ZDLE sequence frameend
  159.  */
  160. static char *Zendnames[] = { "ZCRCE", "ZCRCG", "ZCRCQ", "ZCRCW"};
  161. zsdata(buf, length, frameend)
  162. register char *buf;
  163. {
  164.     register unsigned short crc;
  165.  
  166.     vfile("zsdata: %d %s", length, Zendnames[frameend-ZCRCE&3]);
  167.     if (Crc32t)
  168.         zsda32(buf, length, frameend);
  169.     else {
  170.         crc = 0;
  171.         for (;--length >= 0; ++buf) {
  172.             zsendline(*buf); crc = updcrc((0377 & *buf), crc);
  173.         }
  174.         xsendline(ZDLE); xsendline(frameend);
  175.         crc = updcrc(frameend, crc);
  176.  
  177.         crc = updcrc(0,updcrc(0,crc));
  178.         zsendline(crc>>8); zsendline(crc);
  179.     }
  180.     if (frameend == ZCRCW) {
  181.         xsendline(XON);  flushmo();
  182.     }
  183. }
  184.  
  185. zsda32(buf, length, frameend)
  186. register char *buf;
  187. {
  188.     register int c;
  189.     register UNSL long crc;
  190.  
  191.     crc = 0xFFFFFFFFL;
  192.     for (;--length >= 0; ++buf) {
  193.         c = *buf & 0377;
  194.         if (c & 0140)
  195.             xsendline(lastsent = c);
  196.         else
  197.             zsendline(c);
  198.         crc = UPDC32(c, crc);
  199.     }
  200.     xsendline(ZDLE); xsendline(frameend);
  201.     crc = UPDC32(frameend, crc);
  202.  
  203.     crc = ~crc;
  204.     for (length=4; --length >= 0;) {
  205.         zsendline((int)crc);  crc >>= 8;
  206.     }
  207. }
  208.  
  209. /*
  210.  * Receive array buf of max length with ending ZDLE sequence
  211.  *  and CRC.  Returns the ending character or error code.
  212.  *  NB: On errors may store length+1 bytes!
  213.  */
  214. zrdata(buf, length)
  215. register char *buf;
  216. {
  217.     register int c;
  218.     register unsigned short crc;
  219.     register char *end;
  220.     register int d;
  221.  
  222.     if (Rxframeind == ZBIN32)
  223.         return zrdat32(buf, length);
  224.  
  225.     crc = Rxcount = 0;  end = buf + length;
  226.     while (buf <= end) {
  227.         if ((c = zdlread()) & ~0377) {
  228. crcfoo:
  229.             switch (c) {
  230.             case GOTCRCE:
  231.             case GOTCRCG:
  232.             case GOTCRCQ:
  233.             case GOTCRCW:
  234.                 crc = updcrc((d=c)&0377, crc);
  235.                 if ((c = zdlread()) & ~0377)
  236.                     goto crcfoo;
  237.                 crc = updcrc(c, crc);
  238.                 if ((c = zdlread()) & ~0377)
  239.                     goto crcfoo;
  240.                 crc = updcrc(c, crc);
  241.                 if (crc & 0xFFFF) {
  242.                     zperr(badcrc);
  243.                     return ERROR;
  244.                 }
  245.                 Rxcount = length - (end - buf);
  246.                 vfile("zrdata: %d  %s", Rxcount,
  247.                  Zendnames[d-GOTCRCE&3]);
  248.                 return d;
  249.             case GOTCAN:
  250.                 zperr("Sender Canceled");
  251.                 return ZCAN;
  252.             case TIMEOUT:
  253.                 zperr("TIMEOUT");
  254.                 return c;
  255.             default:
  256.                 zperr("Bad data subpacket");
  257.                 return c;
  258.             }
  259.         }
  260.         *buf++ = c;
  261.         crc = updcrc(c, crc);
  262.     }
  263.     zperr("Data subpacket too long");
  264.     return ERROR;
  265. }
  266.  
  267. zrdat32(buf, length)
  268. register char *buf;
  269. {
  270.     register int c;
  271.     register UNSL long crc;
  272.     register char *end;
  273.     register int d;
  274.  
  275.     crc = 0xFFFFFFFFL;  Rxcount = 0;  end = buf + length;
  276.     while (buf <= end) {
  277.         if ((c = zdlread()) & ~0377) {
  278. crcfoo:
  279.             switch (c) {
  280.             case GOTCRCE:
  281.             case GOTCRCG:
  282.             case GOTCRCQ:
  283.             case GOTCRCW:
  284.                 d = c;  c &= 0377;
  285.                 crc = UPDC32(c, crc);
  286.                 if ((c = zdlread()) & ~0377)
  287.                     goto crcfoo;
  288.                 crc = UPDC32(c, crc);
  289.                 if ((c = zdlread()) & ~0377)
  290.                     goto crcfoo;
  291.                 crc = UPDC32(c, crc);
  292.                 if ((c = zdlread()) & ~0377)
  293.                     goto crcfoo;
  294.                 crc = UPDC32(c, crc);
  295.                 if ((c = zdlread()) & ~0377)
  296.                     goto crcfoo;
  297.                 crc = UPDC32(c, crc);
  298.                 if (crc != 0xDEBB20E3) {
  299.                     zperr(badcrc);
  300.                     return ERROR;
  301.                 }
  302.                 Rxcount = length - (end - buf);
  303.                 vfile("zrdat32: %d %s", Rxcount,
  304.                  Zendnames[d-GOTCRCE&3]);
  305.                 return d;
  306.             case GOTCAN:
  307.                 zperr("Sender Canceled");
  308.                 return ZCAN;
  309.             case TIMEOUT:
  310.                 zperr("TIMEOUT");
  311.                 return c;
  312.             default:
  313.                 zperr("Bad data subpacket");
  314.                 return c;
  315.             }
  316.         }
  317.         *buf++ = c;
  318.         crc = UPDC32(c, crc);
  319.     }
  320.     zperr("Data subpacket too long");
  321.     return ERROR;
  322. }
  323.  
  324.  
  325. /*
  326.  * Read a ZMODEM header to hdr, either binary or hex.
  327.  *  eflag controls local display of non zmodem characters:
  328.  *    0:  no display
  329.  *    1:  display printing characters only
  330.  *    2:  display all non ZMODEM characters
  331.  *  On success, set Zmodem to 1, set Rxpos and return type of header.
  332.  *   Otherwise return negative on error.
  333.  *   Return ERROR instantly if ZCRCW sequence, for fast error recovery.
  334.  */
  335. zgethdr(hdr, eflag)
  336. char *hdr;
  337. {
  338.     register int c, n, cancount;
  339.  
  340.     n = Zrwindow + Baudrate;    /* Max bytes before start of frame */
  341.     Rxframeind = Rxtype = 0;
  342.  
  343. startover:
  344.     cancount = 5;
  345. again:
  346.     /* Return immediate ERROR if ZCRCW sequence seen */
  347.     switch (c = readline(Rxtimeout)) {
  348.     case RCDO:
  349.     case TIMEOUT:
  350.         goto fifi;
  351.     case CAN:
  352. gotcan:
  353.         if (--cancount <= 0) {
  354.             c = ZCAN; goto fifi;
  355.         }
  356.         switch (c = readline(1)) {
  357.         case TIMEOUT:
  358.             goto again;
  359.         case ZCRCW:
  360.             c = ERROR;
  361.         /* **** FALL THRU TO **** */
  362.         case RCDO:
  363.             goto fifi;
  364.         default:
  365.             break;
  366.         case CAN:
  367.             if (--cancount <= 0) {
  368.                 c = ZCAN; goto fifi;
  369.             }
  370.             goto again;
  371.         }
  372.     /* **** FALL THRU TO **** */
  373.     default:
  374. agn2:
  375.         if ( --n == 0) {
  376.             zperr("Garbage count exceeded");
  377.             return(ERROR);
  378.         }
  379.         if (eflag && ((c &= 0177) & 0140))
  380.             bttyout(c);
  381.         else if (eflag > 1)
  382.             bttyout(c);
  383. #ifdef UNIX
  384.         fflush(stderr);
  385. #endif
  386.         goto startover;
  387.     case ZPAD|0200:        /* This is what we want. */
  388.         Not8bit = c;
  389.     case ZPAD:        /* This is what we want. */
  390.         break;
  391.     }
  392.     cancount = 5;
  393. splat:
  394.     switch (c = noxrd7()) {
  395.     case ZPAD:
  396.         goto splat;
  397.     case RCDO:
  398.     case TIMEOUT:
  399.         goto fifi;
  400.     default:
  401.         goto agn2;
  402.     case ZDLE:        /* This is what we want. */
  403.         break;
  404.     }
  405.  
  406.     switch (c = noxrd7()) {
  407.     case RCDO:
  408.     case TIMEOUT:
  409.         goto fifi;
  410.     case ZBIN:
  411.         Rxframeind = ZBIN;  Crc32 = FALSE;
  412.         c =  zrbhdr(hdr);
  413.         break;
  414.     case ZBIN32:
  415.         Crc32 = Rxframeind = ZBIN32;
  416.         c =  zrbhdr32(hdr);
  417.         break;
  418.     case ZHEX:
  419.         Rxframeind = ZHEX;  Crc32 = FALSE;
  420.         c =  zrhhdr(hdr);
  421.         break;
  422.     case CAN:
  423.         goto gotcan;
  424.     default:
  425.         goto agn2;
  426.     }
  427.     Rxpos = hdr[ZP3] & 0377;
  428.     Rxpos = (Rxpos<<8) + (hdr[ZP2] & 0377);
  429.     Rxpos = (Rxpos<<8) + (hdr[ZP1] & 0377);
  430.     Rxpos = (Rxpos<<8) + (hdr[ZP0] & 0377);
  431. fifi:
  432.     switch (c) {
  433.     case GOTCAN:
  434.         c = ZCAN;
  435.     /* **** FALL THRU TO **** */
  436.     case ZNAK:
  437.     case ZCAN:
  438.     case ERROR:
  439.     case TIMEOUT:
  440.     case RCDO:
  441.         zperr("Got %s", frametypes[c+FTOFFSET]);
  442.     /* **** FALL THRU TO **** */
  443.     default:
  444.         if (c >= -3 && c <= FRTYPES)
  445.             vfile("zgethdr: %s %lx", frametypes[c+FTOFFSET], Rxpos);
  446.         else
  447.             vfile("zgethdr: %d %lx", c, Rxpos);
  448.     }
  449.     return c;
  450. }
  451.  
  452. /* Receive a binary style header (type and position) */
  453. zrbhdr(hdr)
  454. register char *hdr;
  455. {
  456.     register int c, n;
  457.     register unsigned short crc;
  458.  
  459.     if ((c = zdlread()) & ~0377)
  460.         return c;
  461.     Rxtype = c;
  462.     crc = updcrc(c, 0);
  463.  
  464.     for (n=4; --n >= 0; ++hdr) {
  465.         if ((c = zdlread()) & ~0377)
  466.             return c;
  467.         crc = updcrc(c, crc);
  468.         *hdr = c;
  469.     }
  470.     if ((c = zdlread()) & ~0377)
  471.         return c;
  472.     crc = updcrc(c, crc);
  473.     if ((c = zdlread()) & ~0377)
  474.         return c;
  475.     crc = updcrc(c, crc);
  476.     if (crc & 0xFFFF) {
  477.         zperr(badcrc);
  478.         return ERROR;
  479.     }
  480. #ifdef ZMODEM
  481.     Protocol = ZMODEM;
  482. #endif
  483.     Zmodem = 1;
  484.     return Rxtype;
  485. }
  486.  
  487. /* Receive a binary style header (type and position) with 32 bit FCS */
  488. zrbhdr32(hdr)
  489. register char *hdr;
  490. {
  491.     register int c, n;
  492.     register UNSL long crc;
  493.  
  494.     if ((c = zdlread()) & ~0377)
  495.         return c;
  496.     Rxtype = c;
  497.     crc = 0xFFFFFFFFL; crc = UPDC32(c, crc);
  498. #ifdef DEBUGZ
  499.     vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  500. #endif
  501.  
  502.     for (n=4; --n >= 0; ++hdr) {
  503.         if ((c = zdlread()) & ~0377)
  504.             return c;
  505.         crc = UPDC32(c, crc);
  506.         *hdr = c;
  507. #ifdef DEBUGZ
  508.         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  509. #endif
  510.     }
  511.     for (n=4; --n >= 0;) {
  512.         if ((c = zdlread()) & ~0377)
  513.             return c;
  514.         crc = UPDC32(c, crc);
  515. #ifdef DEBUGZ
  516.         vfile("zrbhdr32 c=%X  crc=%lX", c, crc);
  517. #endif
  518.     }
  519.     if (crc != 0xDEBB20E3) {
  520.         zperr(badcrc);
  521.         return ERROR;
  522.     }
  523. #ifdef ZMODEM
  524.     Protocol = ZMODEM;
  525. #endif
  526.     Zmodem = 1;
  527.     return Rxtype;
  528. }
  529.  
  530.  
  531. /* Receive a hex style header (type and position) */
  532. zrhhdr(hdr)
  533. char *hdr;
  534. {
  535.     register int c;
  536.     register unsigned short crc;
  537.     register int n;
  538.  
  539.     if ((c = zgethex()) < 0)
  540.         return c;
  541.     Rxtype = c;
  542.     crc = updcrc(c, 0);
  543.  
  544.     for (n=4; --n >= 0; ++hdr) {
  545.         if ((c = zgethex()) < 0)
  546.             return c;
  547.         crc = updcrc(c, crc);
  548.         *hdr = c;
  549.     }
  550.     if ((c = zgethex()) < 0)
  551.         return c;
  552.     crc = updcrc(c, crc);
  553.     if ((c = zgethex()) < 0)
  554.         return c;
  555.     crc = updcrc(c, crc);
  556.     if (crc & 0xFFFF) {
  557.         zperr(badcrc); return ERROR;
  558.     }
  559.     switch ( c = readline(1)) {
  560.     case 0215:
  561.         Not8bit = c;
  562.         /* **** FALL THRU TO **** */
  563.     case 015:
  564.          /* Throw away possible cr/lf */
  565.         switch (c = readline(1)) {
  566.         case 012:
  567.             Not8bit |= c;
  568.         }
  569.     }
  570. #ifdef ZMODEM
  571.     Protocol = ZMODEM;
  572. #endif
  573.     Zmodem = 1; return Rxtype;
  574. }
  575.  
  576. /* Send a byte as two hex digits */
  577. zputhex(c)
  578. register int c;
  579. {
  580.     static char    digits[]    = "0123456789abcdef";
  581.  
  582.     if (Verbose>8)
  583.         vfile("zputhex: %02X", c);
  584.     sendline(digits[(c&0xF0)>>4]);
  585.     sendline(digits[(c)&0xF]);
  586. }
  587.  
  588. /*
  589.  * Send character c with ZMODEM escape sequence encoding.
  590.  *  Escape XON, XOFF. Escape CR following @ (Telenet net escape)
  591.  */
  592. zsendline(c)
  593. {
  594.  
  595.     /* Quick check for non control characters */
  596.     if (c & 0140)
  597.         xsendline(lastsent = c);
  598.     else {
  599.         switch (c &= 0377) {
  600.         case ZDLE:
  601.             xsendline(ZDLE);
  602.             xsendline (lastsent = (c ^= 0100));
  603.             break;
  604.         case 015:
  605.         case 0215:
  606.             if (!Zctlesc && (lastsent & 0177) != '@')
  607.                 goto sendit;
  608.         /* **** FALL THRU TO **** */
  609.         case 020:
  610.         case 021:
  611.         case 023:
  612.         case 0220:
  613.         case 0221:
  614.         case 0223:
  615.             xsendline(ZDLE);
  616.             c ^= 0100;
  617.     sendit:
  618.             xsendline(lastsent = c);
  619.             break;
  620.         default:
  621.             if (Zctlesc && ! (c & 0140)) {
  622.                 xsendline(ZDLE);
  623.                 c ^= 0100;
  624.             }
  625.             xsendline(lastsent = c);
  626.         }
  627.     }
  628. }
  629.  
  630. /* Decode two lower case hex digits into an 8 bit byte value */
  631. zgethex()
  632. {
  633.     register int c;
  634.  
  635.     c = zgeth1();
  636.     if (Verbose>8)
  637.         vfile("zgethex: %02X", c);
  638.     return c;
  639. }
  640. zgeth1()
  641. {
  642.     register int c, n;
  643.  
  644.     if ((c = noxrd7()) < 0)
  645.         return c;
  646.     n = c - '0';
  647.     if (n > 9)
  648.         n -= ('a' - ':');
  649.     if (n & ~0xF)
  650.         return ERROR;
  651.     if ((c = noxrd7()) < 0)
  652.         return c;
  653.     c -= '0';
  654.     if (c > 9)
  655.         c -= ('a' - ':');
  656.     if (c & ~0xF)
  657.         return ERROR;
  658.     c += (n<<4);
  659.     return c;
  660. }
  661.  
  662. /*
  663.  * Read a byte, checking for ZMODEM escape encoding
  664.  *  including CAN*5 which represents a quick abort
  665.  */
  666. zdlread()
  667. {
  668.     register int c;
  669.  
  670. again:
  671.     /* Quick check for non control characters */
  672.     if ((c = readline(Rxtimeout)) & 0140)
  673.         return c;
  674.     switch (c) {
  675.     case ZDLE:
  676.         break;
  677.     case 023:
  678.     case 0223:
  679.     case 021:
  680.     case 0221:
  681.         goto again;
  682.     default:
  683.         if (Zctlesc && !(c & 0140)) {
  684.             goto again;
  685.         }
  686.         return c;
  687.     }
  688. again2:
  689.     if ((c = readline(Rxtimeout)) < 0)
  690.         return c;
  691.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  692.         return c;
  693.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  694.         return c;
  695.     if (c == CAN && (c = readline(Rxtimeout)) < 0)
  696.         return c;
  697.     switch (c) {
  698.     case CAN:
  699.         return GOTCAN;
  700.     case ZCRCE:
  701.     case ZCRCG:
  702.     case ZCRCQ:
  703.     case ZCRCW:
  704.         return (c | GOTOR);
  705.     case ZRUB0:
  706.         return 0177;
  707.     case ZRUB1:
  708.         return 0377;
  709.     case 023:
  710.     case 0223:
  711.     case 021:
  712.     case 0221:
  713.         goto again2;
  714.     default:
  715.         if (Zctlesc && ! (c & 0140)) {
  716.             goto again2;
  717.         }
  718.         if ((c & 0140) ==  0100)
  719.             return (c ^ 0100);
  720.         break;
  721.     }
  722.     if (Verbose>1)
  723.         zperr("Bad escape sequence %x", c);
  724.     return ERROR;
  725. }
  726.  
  727. /*
  728.  * Read a character from the modem line with timeout.
  729.  *  Eat parity, XON and XOFF characters.
  730.  */
  731. noxrd7()
  732. {
  733.     register int c;
  734.  
  735.     for (;;) {
  736.         if ((c = readline(Rxtimeout)) < 0)
  737.             return c;
  738.         switch (c &= 0177) {
  739.         case XON:
  740.         case XOFF:
  741.             continue;
  742.         default:
  743.             if (Zctlesc && !(c & 0140))
  744.                 continue;
  745.         case '\r':
  746.         case '\n':
  747.         case ZDLE:
  748.             return c;
  749.         }
  750.     }
  751. }
  752.  
  753. /* Store long integer pos in Txhdr */
  754. stohdr(pos)
  755. long pos;
  756. {
  757.     Txhdr[ZP0] = pos;
  758.     Txhdr[ZP1] = pos>>8;
  759.     Txhdr[ZP2] = pos>>16;
  760.     Txhdr[ZP3] = pos>>24;
  761. }
  762.  
  763. /* Recover a long integer from a header */
  764. long
  765. rclhdr(hdr)
  766. register char *hdr;
  767. {
  768.     register long l;
  769.  
  770.     l = (hdr[ZP3] & 0377);
  771.     l = (l << 8) | (hdr[ZP2] & 0377);
  772.     l = (l << 8) | (hdr[ZP1] & 0377);
  773.     l = (l << 8) | (hdr[ZP0] & 0377);
  774.     return l;
  775. }
  776.  
  777. /* End of zm.c */
  778.